diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000000..fdd45e2e15a --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,345 @@ +on: push + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + checkapply: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + # to debug container live from GitHub + # - uses: mxschmitt/action-tmate@v3 + - run: bash -c '[ ! -f shazam.log ] || { cat shazam.log; exit 1; }' + + checkpatch-ignore-signoff: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: git fetch -a origin --unshallow || true + - run: git remote add upstream -f https://gitlab.com/qemu-project/qemu + - run: ./scripts/checkpatch.pl --no-signoff $(git merge-base upstream/master HEAD)..HEAD + + checkpatch-with-signoff: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: git fetch -a origin --unshallow || true + - run: git remote add upstream -f https://gitlab.com/qemu-project/qemu + - run: ./scripts/checkpatch.pl $(git merge-base upstream/master HEAD)..HEAD + + # use docker-run to not rebuild images + # images are built daily and pushed on pbolinaro/qemu-ci:* + build-cross: + needs: checkapply + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + container: [alpine,centos9,debian,debian-all-test-cross,debian-amd64-cross,debian-arm64-cross,debian-armhf-cross,debian-hexagon-cross,debian-i686-cross,debian-legacy-test-cross,debian-loongarch-cross,debian-mips64el-cross,debian-mipsel-cross,debian-ppc64el-cross,debian-riscv64-cross,debian-s390x-cross,debian-tricore-cross,fedora,fedora-rust-nightly,opensuse-leap,ubuntu2204] + steps: + - uses: actions/checkout@v4 + - run: pip install meson + - run: make docker-run J=$(nproc) RUNC=podman TEST=test-build IMAGE=docker.io/pbolinaro/qemu-ci:${{matrix.container}} + + build: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx './configure && ninja -C build install' + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + ./build/qemu-system-x86_64 -nographic -plugin ./build/contrib/plugins/libstoptrigger,icount=1000000 -plugin ./build/tests/tcg/plugins/libinsn -d plugin + + build-cross-mingw64: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:fedora-win64-cross + bash -cx './configure $QEMU_CONFIGURE_OPTS && ninja -C build install' + + build-windows: + needs: checkapply + runs-on: windows-2025 + strategy: + fail-fast: false + matrix: + sys: [UCRT64, CLANG64, MINGW64] + defaults: + run: + shell: msys2 {0} + steps: + - uses: msys2/setup-msys2@v2 + with: + update: true + msystem: ${{matrix.sys}} + - run: pacman -S --noconfirm curl git + - uses: actions/checkout@v4 + - run: > + pacman -S --noconfirm + base-devel binutils bison diffutils flex git grep make sed + ${MINGW_PACKAGE_PREFIX}-toolchain + ${MINGW_PACKAGE_PREFIX}-glib2 + ${MINGW_PACKAGE_PREFIX}-gtk3 + ${MINGW_PACKAGE_PREFIX}-libnfs + ${MINGW_PACKAGE_PREFIX}-libssh + ${MINGW_PACKAGE_PREFIX}-ninja + ${MINGW_PACKAGE_PREFIX}-pixman + ${MINGW_PACKAGE_PREFIX}-pkgconf + ${MINGW_PACKAGE_PREFIX}-python + ${MINGW_PACKAGE_PREFIX}-SDL2 + ${MINGW_PACKAGE_PREFIX}-zstd + - run: ./configure && ninja -C build + - run: ./build/qemu-system-x86_64 -nographic -plugin ./build/contrib/plugins/libstoptrigger,icount=1000000 -plugin ./build/tests/tcg/plugins/libinsn -d plugin + + build-macos-x86_64: + needs: checkapply + runs-on: macos-13 + steps: + - uses: actions/checkout@v4 + - run: brew install --quiet $(brew deps --include-build qemu) || true + # on macos, werror is not on by default + - run: ./configure --enable-werror && ninja -C build + - run: ./build/qemu-system-x86_64 -nographic -plugin ./build/contrib/plugins/libstoptrigger,icount=1000000 -plugin ./build/tests/tcg/plugins/libinsn -d plugin + + build-macos-aarch64: + needs: checkapply + runs-on: macos-14 + steps: + - uses: actions/checkout@v4 + - run: brew install --quiet $(brew deps --include-build qemu) || true + # on macos, werror is not on by default + - run: ./configure --enable-werror && ninja -C build + - run: ./build/qemu-system-x86_64 -nographic -plugin ./build/contrib/plugins/libstoptrigger,icount=1000000 -plugin ./build/tests/tcg/plugins/libinsn -d plugin + + build-misc: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx './configure --disable-user --disable-system --enable-docs --enable-tools && ninja -C build install' + + build-32bits: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-i686-cross + bash -cx './configure $QEMU_CONFIGURE_OPTS && ninja -C build install' + + build-big-endian: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-s390x-cross + bash -cx './configure $QEMU_CONFIGURE_OPTS && ninja -C build install' + + build-debug: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx './configure --enable-debug --enable-asan --enable-ubsan && ninja -C build install' + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + ./build/qemu-system-x86_64 -nographic -plugin ./build/contrib/plugins/libstoptrigger,icount=1000000 -plugin ./build/tests/tcg/plugins/libinsn -d plugin + + build-static: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx './configure --disable-system --disable-tools --disable-guest-agent --disable-docs --static && ninja -C build install' + + build-tsan: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx './configure --enable-tsan && ninja -C build install' + + build-clang: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx './configure --cxx=clang++ --cc=clang --host-cc=clang && ninja -C build install' + + build-clang-latest: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx 'LLVM_VERSION=19 && apt update && apt install -y lsb-release wget software-properties-common gnupg && wget https://apt.llvm.org/llvm.sh && bash llvm.sh ${LLVM_VERSION} && ./configure --cxx=clang++-${LLVM_VERSION} --cc=clang-${LLVM_VERSION} --host-cc=clang-${LLVM_VERSION} && ninja -C build install' + + build-rust: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx './configure --enable-rust && ninja -C build install' + + build-disable-tcg: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx './configure --disable-tcg && ninja -C build install' + + build-disable-kvm: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx './configure --disable-kvm && ninja -C build install' + + build-disable-tcg-kvm-for-xen: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx './configure --disable-tcg --disable-kvm && ninja -C build install' + + build-minimal: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian + bash -cx './configure --without-default-features --without-default-devices --disable-kvm --disable-tcg && ninja -C build install' + + check-tcg: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-all-test-cross + bash -cx './configure --disable-docs --enable-debug-tcg --enable-debug-graph-lock --enable-debug-mutex --enable-asan --enable-ubsan && ninja -C build' + - run: > + podman run --init --privileged --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-all-test-cross + bash -cx "env ASAN_OPTIONS=detect_leaks=0 make -k -j $(nproc) check-tcg" + + # run all meson tests, except functional. + # block tests are not ran because they don't support sanitizers: + # https://gitlab.com/qemu-project/qemu/-/blob/master/tests/qemu-iotests/meson.build + check: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + # we use image with download cache filled. Solves servers flakiness. + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-precache-tests + bash -cx './configure --disable-docs --enable-debug-tcg --enable-debug-graph-lock --enable-debug-mutex --enable-asan --enable-ubsan && ninja -C build' + - run: sudo chown $USER:$USER /dev/kvm + - run: > + podman run --init --privileged --rm -i -v /dev/kvm:/dev/kvm -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-precache-tests + bash -cx "env ASAN_OPTIONS=detect_leaks=0 ./build/pyvenv/bin/meson test -C build --setup thorough --no-suite func-quick --no-suite func-thorough -t 5 --print-errorlogs" + + check-functional: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + # we clean up runner first, to get more disk space + - run: docker system prune -af && sudo rm -rf /opt/* + - uses: actions/checkout@v4 + # we use image with download cache filled. Solves servers flakiness. + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-precache-tests + bash -cx './configure --disable-docs --enable-debug-tcg --enable-debug-graph-lock --enable-debug-mutex --enable-asan --enable-ubsan && ninja -C build' + - run: sudo chown $USER:$USER /dev/kvm + - run: > + podman run --init --privileged --rm -i -v /dev/kvm:/dev/kvm -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-precache-tests + bash -cx "env ASAN_OPTIONS=detect_leaks=0 ./build/pyvenv/bin/meson test -C build --setup thorough --suite func-quick --suite func-thorough -j $(($(nproc) / 2)) -t 5 --print-errorlogs --wrapper $(pwd)/scripts/run-functional-test.sh --max-lines=0" + # Limit parallelism because it creates timeout. + + # iotests do not support sanitizers, so we run them in their own job + check-block: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + # we use image with download cache filled. Solves servers flakiness. + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-precache-tests + bash -cx './configure --disable-docs --enable-debug-tcg --enable-debug-graph-lock --enable-debug-mutex && ninja -C build' + - run: sudo chown $USER:$USER /dev/kvm + - run: > + podman run --init --privileged --rm -i -v /dev/kvm:/dev/kvm -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-precache-tests + bash -cx "./build/pyvenv/bin/meson test -C build --setup thorough --suite block --suite block-slow --suite block-thorough -t 5 --print-errorlogs" + + check-avocado: + needs: checkapply + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + # add more time for all tests + - run: sed -i -e 's/timeout = .*/timeout = 3600/' $(find tests/avocado/ -type f) + # we use image with download cache filled. Solves servers flakiness. + - run: > + podman run --init --rm -it -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-precache-tests + bash -cx './configure --disable-docs --enable-debug-tcg --enable-debug-graph-lock --enable-debug-mutex --enable-asan --enable-ubsan && ninja -C build' + - run: sudo chown $USER:$USER /dev/kvm + - run: > + podman run --init --privileged --rm -it -v /dev/kvm:/dev/kvm -v $(pwd):$(pwd) -w $(pwd) + docker.io/pbolinaro/qemu-ci:debian-precache-tests + bash -cx "env ASAN_OPTIONS=detect_leaks=0 make -k check-avocado V=1" diff --git a/.github/workflows/containers.yml b/.github/workflows/containers.yml new file mode 100644 index 00000000000..d4076b8415c --- /dev/null +++ b/.github/workflows/containers.yml @@ -0,0 +1,41 @@ +on: + schedule: + - cron: '0 6 * * *' + workflow_dispatch: + +permissions: write-all + +jobs: + build_container: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + # cd tests/docker/dockerfiles/ + # ls *docker | sed -e 's/.docker//' | tr '\n' ',' + # remove: debian-bootstrap,debian-toolchain + container: [alpine,centos9,debian-all-test-cross,debian-amd64-cross,debian-arm64-cross,debian-armhf-cross,debian,debian-hexagon-cross,debian-i686-cross,debian-legacy-test-cross,debian-loongarch-cross,debian-mips64el-cross,debian-mipsel-cross,debian-ppc64el-cross,debian-riscv64-cross,debian-s390x-cross,debian-tricore-cross,debian-xtensa-cross,fedora,fedora-rust-nightly,fedora-win64-cross,opensuse-leap,python,ubuntu2204] + steps: + - uses: actions/checkout@v4 + - run: make docker-image-${{matrix.container}} RUNC=podman V=1 + - run: podman tag qemu/${{matrix.container}} docker.io/pbolinaro/qemu-ci:${{matrix.container}} + - run: podman login -u pbolinaro -p ${{secrets.DOCKERHUB_PASSWORD}} + - run: podman push docker.io/pbolinaro/qemu-ci:${{matrix.container}} + + build_container_debian-precache-tests: + runs-on: ubuntu-24.04 + steps: + # we clean up runner first, to get more disk space + - run: docker system prune -af && sudo rm -rf /opt/* + - uses: actions/checkout@v4 + - run: make docker-image-debian RUNC=podman V=1 + # fill download cache for functional and check-avocado + # running check-avocado without any qemu binary will only download data + # in /root/avocado + - run: > + podman run -it -v $(pwd):$(pwd) -w $(pwd) qemu/debian + ./precache_tests.sh + # commit result as a new image. Cache will be in /root/.cache and /root/avocado + - run: podman commit "$(podman ps -aq)" docker.io/pbolinaro/qemu-ci:debian-precache-tests + - run: podman login -u pbolinaro -p ${{secrets.DOCKERHUB_PASSWORD}} + - run: podman push docker.io/pbolinaro/qemu-ci:debian-precache-tests diff --git a/.github/workflows/new_series.yml b/.github/workflows/new_series.yml new file mode 100644 index 00000000000..1ad8ba9ec7d --- /dev/null +++ b/.github/workflows/new_series.yml @@ -0,0 +1,27 @@ +on: + schedule: + - cron: '*/10 * * * *' + workflow_dispatch: + +permissions: write-all + +jobs: + push_new_series: + runs-on: ubuntu-24.04 + concurrency: + group: push_new_series + cancel-in-progress: true + steps: + - name: checkout + uses: actions/checkout@v3 + with: + # a PAT must be generated with workflow permission, else it's not + # possible to push any change for those files + # https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/triggering-a-workflow#triggering-a-workflow-from-a-workflow + token: ${{ secrets.WORKFLOW_COMMIT_TOKEN }} + - run: git fetch -a origin --unshallow || true + - run: git config user.name "GitHub Actions Bot" + - run: git config user.email "" + - run: git config advice.detachedHead false + - run: sudo pip install b4 + - run: ./push_new_series.sh diff --git a/.github/workflows/upstream.yml b/.github/workflows/upstream.yml new file mode 100644 index 00000000000..dbae2676f34 --- /dev/null +++ b/.github/workflows/upstream.yml @@ -0,0 +1,19 @@ +on: + schedule: + - cron: '0 */2 * * *' + workflow_dispatch: + +permissions: write-all + +jobs: + push_upstream: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: git fetch -a origin --unshallow || true + - run: git config user.name "GitHub Actions Bot" + - run: git config user.email "" + - run: git checkout ci + - run: git remote add upstream -f https://gitlab.com/qemu-project/qemu + - run: git rebase upstream/master + - run: git push -f --set-upstream origin "ci:upstream" diff --git a/block/vvfat.c b/block/vvfat.c index 8ffe8b3b9bf..626c4f01635 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -255,6 +255,17 @@ typedef struct direntry_t { uint32_t size; } QEMU_PACKED direntry_t; +typedef struct lfn_direntry_t { + uint8_t sequence; + uint8_t name01[10]; + uint8_t attributes; + uint8_t direntry_type; + uint8_t sfn_checksum; + uint8_t name0e[12]; + uint16_t begin; + uint8_t name1c[4]; +} QEMU_PACKED lfn_direntry_t; + /* this structure are used to transparently access the files */ typedef struct mapping_t { @@ -399,11 +410,28 @@ static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs) /* direntry functions */ +static void write_long_filename(lfn_direntry_t *entry, int index, uint8_t c) +{ + if (index < ARRAY_SIZE(entry->name01)) { + entry->name01[index] = c; + return; + } + index -= ARRAY_SIZE(entry->name01); + if (index < ARRAY_SIZE(entry->name0e)) { + entry->name0e[index] = c; + return; + } + index -= ARRAY_SIZE(entry->name0e); + if (index < ARRAY_SIZE(entry->name1c)) { + entry->name1c[index] = c; + } +} + static direntry_t *create_long_filename(BDRVVVFATState *s, const char *filename) { int number_of_entries, i; glong length; - direntry_t *entry; + lfn_direntry_t *entry; gunichar2 *longname = g_utf8_to_utf16(filename, -1, NULL, &length, NULL); if (!longname) { @@ -415,24 +443,23 @@ static direntry_t *create_long_filename(BDRVVVFATState *s, const char *filename) for(i=0;idirectory)); + entry->sequence = (number_of_entries - i) | (i == 0 ? 0x40 : 0); entry->attributes=0xf; - entry->reserved[0]=0; + entry->direntry_type = 0; entry->begin=0; - entry->name[0]=(number_of_entries-i)|(i==0?0x40:0); - } - for(i=0;i<26*number_of_entries;i++) { - int offset=(i%26); - if(offset<10) offset=1+offset; - else if(offset<22) offset=14+offset-10; - else offset=28+offset-22; - entry=array_get(&(s->directory),s->directory.next-1-(i/26)); + } + for (i = 0; i < 26 * number_of_entries; i++) { + uint8_t c; + + entry = array_get(&s->directory, s->directory.next - i / 26 - 1); if (i >= 2 * length + 2) { - entry->name[offset] = 0xff; + c = 0xff; } else if (i % 2 == 0) { - entry->name[offset] = longname[i / 2] & 0xff; + c = longname[i / 2] & 0xff; } else { - entry->name[offset] = longname[i / 2] >> 8; + c = longname[i / 2] >> 8; } + write_long_filename(entry, i % 26, c); } g_free(longname); return array_get(&(s->directory),s->directory.next-number_of_entries); @@ -731,7 +758,7 @@ static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s, /* calculate anew, because realloc could have taken place */ entry_long=array_get(&(s->directory),long_index); while(entry_longreserved[1]=chksum; + ((lfn_direntry_t *)entry_long)->sfn_checksum = chksum; entry_long++; } } diff --git a/precache_tests.sh b/precache_tests.sh new file mode 100755 index 00000000000..0664294ea99 --- /dev/null +++ b/precache_tests.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +set -euo pipefail + +check_avocado_cache() +{ + # avocado will keep in cache incomplete images, and there is no way to force + # it to redownload it... So we do this checking ourselves here. + + if [ ! -d $HOME/avocado ]; then + echo "missing $HOME/avocado" + return 1 + fi + + err=0 + for expected in $(find $HOME/avocado -type f | grep CHECKSUM | sort); do + file=$(echo $expected | sed -e 's/-CHECKSUM//') + hash_type=$(cat $expected | cut -f 1 -d ' ') + if [ ! -f "$file" ]; then + echo $file is missing + err=1 + continue + fi + hash=$(${hash_type}sum $file | cut -f 1 -d ' ') + if ! diff <(cat $expected) <(echo $hash_type $hash); then + echo $file has hash mismatch - delete + rm -rf "$(dirname "$file")" + err=1 + fi + done + return $err +} + +./configure +ninja -C build precache-functional -k 0 || +ninja -C build -j1 precache-functional -k 0 + +# avocado fetch assets will sometimes fail with exception, but without any error +# code. In this case, either an item is missing, or it's in the cache but with a +# bad hash. In the second case, avocado does not redownload it... :( +while true; do + make -C build check-avocado SPEED=slow |& tee avocado.log + echo ----------------------------------------- + if ! check_avocado_cache; then + echo "avocado cache has missing items" + continue + fi + if grep -A 20 -i Traceback avocado.log; then + echo "exception while running avocado" + continue + fi + echo "avocado cache is now ready" + break +done diff --git a/push_new_series.sh b/push_new_series.sh new file mode 100755 index 00000000000..ee6903fa4d4 --- /dev/null +++ b/push_new_series.sh @@ -0,0 +1,156 @@ +#!/usr/bin/env bash + +set -euo pipefail + +die() +{ + echo 1>&2 "$@" + exit 1 +} + +# return URL for mailboxes for previous, current and next month. This way, we +# don't miss any email, even with different timezones. +mailbox_archives() +{ + current_date=$1 + + current_month=$(date +%m --date "$current_date") + current_year=$(date +%Y --date "$current_date") + previous_year=$current_year + next_year=$current_year + previous_month=$(printf "%02d" $((current_month - 1))) + next_month=$(printf "%02d" $((current_month + 1))) + + if [ $current_month == "01" ]; then + previous_month=12 + previous_year=$((current_year - 1)) + elif [ $current_month == "12" ]; then + next_month=01 + next_year=$((current_year + 1)) + fi + + qemu_archive="https://lists.gnu.org/archive/mbox/qemu-devel/" + echo $qemu_archive$previous_year-$previous_month \ + $qemu_archive$current_year-$current_month \ + $qemu_archive$next_year-$next_month +} + +# download all emails for previous, current and next month. +fetch_mails() +{ + out=$1 + rm -rf $out + mkdir -p $out + mkdir -p $out.mailbox + pushd $out.mailbox + archives=$(mailbox_archives "$(date)") + # we can have missing current or next mailbox depending on timezone + wget --no-verbose --no-clobber $archives || true + popd + git mailsplit -o$out $out.mailbox/* +} + +find_series() +{ + mail_dir=$1 + # find all message id, for mails without a reference (i.e. first in series). + grep -Lri '^References: .' $mail_dir | sort | while read m + do + # skip messages replying to thread + if grep -qi '^In-Reply-to: .' $m; then + continue + fi + msg_id=$(grep -i '^message-id: ' $m | head -n1 | + sed -e 's/.*$//') + date=$(grep -i '^date: ' $m | head -n1 | sed -e 's/^date: //I') + echo "$msg_id|$date" + done +} + +fetch_repositories() +{ + git remote remove upstream || true + git remote add upstream -f https://gitlab.com/qemu-project/qemu + git fetch -a origin -p +} + +push_one_series() +{ + s="$1"; shift + apply_revision="$1"; shift + echo "-----------------------------------------------------------------" + msg_id=$(echo "$s" | cut -f 1 -d '|') + date=$(echo "$s" | cut -f 2 -d '|') + echo "$msg_id | $date" + if git rev-parse "remotes/origin/$msg_id" >& /dev/null; then + return + fi + + # find git commit on master close to date of series + base_git_revision=$(git log -n1 --format=format:%H --before="$date" \ + --first-parent upstream/master) + echo "push this new series, applied from $base_git_revision" + git checkout "$base_git_revision" >& /dev/null + git branch -D new_series >& /dev/null || true + git checkout -b new_series + + # apply series + if ! b4 shazam --allow-unicode-control-chars $msg_id |& tee shazam.log; then + git am --abort || true + git add shazam.log + git commit -m 'b4 shazam failed' + fi + + if grep -qi 'message-id is not known' shazam.log; then + echo "no thread found for: $msg_id" + return + fi + + if grep -qi 'no patches found' shazam.log; then + echo "no patches found in series: $msg_id" + return + fi + + if grep -qi 'ERROR: missing' shazam.log; then + # try again next time, let time for lore server to receive all patches + echo "missing patches in series: $msg_id" + return + fi + + rm -f ./*.mbx + b4 mbox "$msg_id" --single-message + subject=$(grep -i '^Subject:' *.mbx | sed -e 's/Subject:\s*//') + + if echo "$subject" | grep -i "^Re:"; then + echo "this message has no reference but is an answer: $msg_id" + return + fi + + git push --set-upstream origin "new_series:$msg_id" + cat > commit_msg << EOF +$subject + +https://lore.kernel.org/qemu-devel/$msg_id + +--- + +$(grep -A 100000 -i '^From:' *.mbx) +EOF + # apply a specific patch + if [ "$apply_revision" != "" ]; then + git cherry-pick "$apply_revision" --no-commit + git commit -a -F commit_msg --signoff + fi + # let some time to GitHub to order branches + sleep 5 + git push --set-upstream origin "new_series:${msg_id}_ci" +} + +fetch_repositories +apply_range=$(git merge-base origin/ci upstream/master) +[ "$apply_range" != "" ] || die "can't find revisions to apply to series" +# apply all commits on ci branch +apply_range=$apply_range..origin/ci + +fetch_mails mails +find_series mails | while read s; do push_one_series "$s" "$apply_range"; done diff --git a/scripts/run-functional-test.sh b/scripts/run-functional-test.sh new file mode 100755 index 00000000000..bba85d8789d --- /dev/null +++ b/scripts/run-functional-test.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -euo pipefail + +test=$(basename "$*" .py) + +stop() +{ + test_dir=$(find tests/functional -name "$test"'.*') + for log in "$test_dir"/*.log; do + cat >&2 << EOF +----------------------------------------------------- +$(echo $log) +$(tail -n 100 $log) +EOF + done + cat >&2 << EOF +EOF +} + +trap stop SIGTERM + +"$@" diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index a323606e5a9..4ccc0306da0 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -465,6 +465,7 @@ void helper_invtlb_page_asid_or_g(CPULoongArchState *env, tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN); vpn = (addr & TARGET_VIRT_MASK) >> (tlb_ps + 1); compare_shift = tlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT; + compare_shift = MIN(63, compare_shift); if ((tlb_g || (tlb_asid == asid)) && (vpn == (tlb_vppn >> compare_shift))) { diff --git a/tests/avocado/kvm_xen_guest.py b/tests/avocado/kvm_xen_guest.py index f8cb458d5db..910e7b075b2 100644 --- a/tests/avocado/kvm_xen_guest.py +++ b/tests/avocado/kvm_xen_guest.py @@ -158,14 +158,14 @@ def test_kvm_xen_guest_novector_nomsi(self): self.run_and_check() self.ssh_command('grep xen-platform-pci /proc/interrupts') - def test_kvm_xen_guest_novector_noapic(self): - """ - :avocado: tags=kvm_xen_guest_novector_noapic - """ - - self.common_vm_setup() - self.kernel_params = (self.KERNEL_DEFAULT + - ' xen_emul_unplug=ide-disks' + - ' xen_no_vector_callback noapic') - self.run_and_check() - self.ssh_command('grep xen-platform-pci /proc/interrupts') + #def test_kvm_xen_guest_novector_noapic(self): + # """ + # :avocado: tags=kvm_xen_guest_novector_noapic + # """ + + # self.common_vm_setup() + # self.kernel_params = (self.KERNEL_DEFAULT + + # ' xen_emul_unplug=ide-disks' + + # ' xen_no_vector_callback noapic') + # self.run_and_check() + # self.ssh_command('grep xen-platform-pci /proc/interrupts') diff --git a/tests/avocado/replay_kernel.py b/tests/avocado/replay_kernel.py index e22c200a368..64d63a00fa1 100644 --- a/tests/avocado/replay_kernel.py +++ b/tests/avocado/replay_kernel.py @@ -320,23 +320,24 @@ def test_ppc64_powernv(self): console_pattern = 'VFS: Cannot open root device' self.run_rr(kernel_path, kernel_command_line, console_pattern) - def test_m68k_q800(self): - """ - :avocado: tags=arch:m68k - :avocado: tags=machine:q800 - """ - deb_url = ('https://snapshot.debian.org/archive/debian-ports' - '/20191021T083923Z/pool-m68k/main' - '/l/linux/kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb') - deb_hash = '044954bb9be4160a3ce81f8bc1b5e856b75cccd1' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinux-5.3.0-1-m68k') - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0 vga=off') - console_pattern = 'No filesystem could mount root' - self.run_rr(kernel_path, kernel_command_line, console_pattern) + # This test needs a sound card available, but we can't get one on GitHub. + #def test_m68k_q800(self): + # """ + # :avocado: tags=arch:m68k + # :avocado: tags=machine:q800 + # """ + # deb_url = ('https://snapshot.debian.org/archive/debian-ports' + # '/20191021T083923Z/pool-m68k/main' + # '/l/linux/kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb') + # deb_hash = '044954bb9be4160a3ce81f8bc1b5e856b75cccd1' + # deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + # kernel_path = self.extract_from_deb(deb_path, + # '/boot/vmlinux-5.3.0-1-m68k') + + # kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + # 'console=ttyS0 vga=off') + # console_pattern = 'No filesystem could mount root' + # self.run_rr(kernel_path, kernel_command_line, console_pattern) def do_test_advcal_2018(self, file_path, kernel_name, args=None): archive.extract(file_path, self.workdir) diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker index 4d5fb3e3a14..8f714ad7ef8 100644 --- a/tests/docker/dockerfiles/opensuse-leap.docker +++ b/tests/docker/dockerfiles/opensuse-leap.docker @@ -6,6 +6,10 @@ FROM registry.opensuse.org/opensuse/leap:15.6 +# This package update tries to chown /dev/zero, which result in error with +# podman rootless container. +RUN zypper al permissions + RUN zypper update -y && \ zypper addrepo -fc https://download.opensuse.org/update/leap/15.6/backports/openSUSE:Backports:SLE-15-SP6:Update.repo && \ zypper install -y \ diff --git a/tests/functional/meson.build b/tests/functional/meson.build index cf80924ddc3..e0f0d2705ba 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -123,7 +123,7 @@ tests_loongarch64_system_thorough = [ tests_m68k_system_thorough = [ 'm68k_mcf5208evb', 'm68k_nextcube', - 'm68k_q800', + # 'm68k_q800', # this test needs a soundcard, not available on GitHub 'm68k_tuxrun', ] diff --git a/tests/qemu-iotests/181 b/tests/qemu-iotests/181 deleted file mode 100755 index dc90a10757f..00000000000 --- a/tests/qemu-iotests/181 +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env bash -# group: rw auto migration quick -# -# Test postcopy live migration with shared storage -# -# Copyright (C) 2017 Red Hat, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -# creator -owner=kwolf@redhat.com - -seq=`basename $0` -echo "QA output created by $seq" - -status=1 # failure is the default! - -MIG_SOCKET="${SOCK_DIR}/migrate" - -_cleanup() -{ - rm -f "${MIG_SOCKET}" - _cleanup_test_img - _cleanup_qemu -} -trap "_cleanup; exit \$status" 0 1 2 3 15 - -# get standard environment, filters and checks -. ./common.rc -. ./common.filter -. ./common.qemu - -_supported_fmt generic -# Formats that do not support live migration -_unsupported_fmt qcow vdi vhdx vmdk vpc vvfat parallels -_supported_proto generic -_supported_os Linux - -size=64M -_make_test_img $size - -echo -echo === Starting VMs === -echo - -qemu_comm_method="monitor" - -if [ "$IMGOPTSSYNTAX" = "true" ]; then - _launch_qemu \ - -drive "${TEST_IMG}",cache=${CACHEMODE},aio=$AIOMODE,id=disk -else - _launch_qemu \ - -drive file="${TEST_IMG}",cache=${CACHEMODE},aio=$AIOMODE,driver=$IMGFMT,id=disk -fi -src=$QEMU_HANDLE - -if [ "$IMGOPTSSYNTAX" = "true" ]; then - _launch_qemu \ - -drive "${TEST_IMG}",cache=${CACHEMODE},aio=$AIOMODE,id=disk \ - -incoming "unix:${MIG_SOCKET}" -else - _launch_qemu \ - -drive file="${TEST_IMG}",cache=${CACHEMODE},aio=$AIOMODE,driver=$IMGFMT,id=disk \ - -incoming "unix:${MIG_SOCKET}" -fi -dest=$QEMU_HANDLE - -echo -echo === Write something on the source === -echo - -silent= -_send_qemu_cmd $src 'qemu-io disk "write -P 0x55 0 64k"' "(qemu)" -_send_qemu_cmd $src "" "ops/sec" -_send_qemu_cmd $src 'qemu-io disk "read -P 0x55 0 64k"' "(qemu)" -_send_qemu_cmd $src "" "ops/sec" - -echo -echo === Do postcopy migration to destination === -echo - -# Slow down migration so much that it definitely won't finish before we can -# switch to postcopy -# Enable postcopy-ram capability both on source and destination -silent=yes -_send_qemu_cmd $dest 'migrate_set_capability postcopy-ram on' "(qemu)" - -qemu_error_no_exit=yes success_or_failure=yes \ - _send_qemu_cmd $dest '' "(qemu)" "Postcopy is not supported" -if [ ${QEMU_STATUS[$dest]} -lt 0 ]; then - _send_qemu_cmd $dest '' "(qemu)" - - _send_qemu_cmd $src 'quit' "" - _send_qemu_cmd $dest 'quit' "" - wait=1 _cleanup_qemu - - _notrun 'Postcopy is not supported' -fi - -_send_qemu_cmd $src 'migrate_set_parameter max-bandwidth 4k' "(qemu)" -_send_qemu_cmd $src 'migrate_set_capability postcopy-ram on' "(qemu)" -_send_qemu_cmd $src "migrate -d unix:${MIG_SOCKET}" "(qemu)" -_send_qemu_cmd $src 'migrate_start_postcopy' "(qemu)" - -QEMU_COMM_TIMEOUT=1 qemu_cmd_repeat=10 silent=yes \ - _send_qemu_cmd $src "info migrate" "completed\|failed" -silent=yes _send_qemu_cmd $src "" "(qemu)" - -echo -echo === Do some I/O on the destination === -echo - -# It is important that we use the BlockBackend of the guest device here instead -# of the node name, which would create a new BlockBackend and not test whether -# the guest has the necessary permissions to access the image now -silent= -_send_qemu_cmd $dest 'qemu-io disk "read -P 0x55 0 64k"' "(qemu)" -_send_qemu_cmd $dest "" "ops/sec" -_send_qemu_cmd $dest 'qemu-io disk "write -P 0x66 1M 64k"' "(qemu)" -_send_qemu_cmd $dest "" "ops/sec" - -echo -echo === Shut down and check image === -echo - -_send_qemu_cmd $src 'quit' "" -_send_qemu_cmd $dest 'quit' "" -wait=1 _cleanup_qemu - -_check_test_img - -# success, all done -echo "*** done" -rm -f $seq.full -status=0 diff --git a/tests/qemu-iotests/181.out b/tests/qemu-iotests/181.out deleted file mode 100644 index d58c6a9dabb..00000000000 --- a/tests/qemu-iotests/181.out +++ /dev/null @@ -1,37 +0,0 @@ -QA output created by 181 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 - -=== Starting VMs === - - -=== Write something on the source === - -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) qemu-io disk "write -P 0x55 0 64k" -wrote 65536/65536 bytes at offset 0 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) -(qemu) qemu-io disk "read -P 0x55 0 64k" -read 65536/65536 bytes at offset 0 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) - -=== Do postcopy migration to destination === - - -=== Do some I/O on the destination === - -(qemu) qemu-io disk "read -P 0x55 0 64k" -read 65536/65536 bytes at offset 0 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) -(qemu) qemu-io disk "write -P 0x66 1M 64k" -wrote 65536/65536 bytes at offset 1048576 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) - -=== Shut down and check image === - -(qemu) quit -(qemu) -(qemu) quit -No errors were found on the image. -*** done diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 94b28e5a534..e3dface3c19 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -5,7 +5,7 @@ slow_qtests = { 'cdrom-test' : 610, 'device-introspect-test' : 720, 'ide-test' : 120, - 'migration-test' : 480, + # 'migration-test' : 480, 'npcm7xx_pwm-test': 300, 'npcm7xx_watchdog_timer-test': 120, 'qmp-cmd-test' : 120, @@ -112,7 +112,7 @@ qtests_i386 = \ 'device-plug-test', 'drive_del-test', 'cpu-plug-test', - 'migration-test', + # 'migration-test', ] if dbus_display and config_all_devices.has_key('CONFIG_VGA') @@ -186,7 +186,8 @@ qtests_ppc64 = \ (slirp.found() ? ['pxe-test'] : []) + \ (config_all_devices.has_key('CONFIG_USB_UHCI') ? ['usb-hcd-uhci-test'] : []) + \ (config_all_devices.has_key('CONFIG_USB_XHCI_NEC') ? ['usb-hcd-xhci-test'] : []) + \ - qtests_pci + ['migration-test', 'cpu-plug-test', 'drive_del-test'] + qtests_pci + ['cpu-plug-test', 'drive_del-test'] + #qtests_pci + ['migration-test', 'cpu-plug-test', 'drive_del-test'] qtests_sh4 = (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) qtests_sh4eb = (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) @@ -260,7 +261,8 @@ qtests_aarch64 = \ ['arm-cpu-features', 'numa-test', 'boot-serial-test', - 'migration-test'] + ] + #'migration-test'] qtests_s390x = \ qtests_filter + \ @@ -269,7 +271,8 @@ qtests_s390x = \ 'device-plug-test', 'virtio-ccw-test', 'cpu-plug-test', - 'migration-test'] + ] + #'migration-test'] qtests_riscv32 = \ (config_all_devices.has_key('CONFIG_SIFIVE_E_AON') ? ['sifive-e-aon-watchdog-test'] : []) @@ -363,7 +366,7 @@ qtests = { 'migration/migration-util.c') + dbus_vmstate1, 'erst-test': files('erst-test.c'), 'ivshmem-test': [rt, '../../contrib/ivshmem-server/ivshmem-server.c'], - 'migration-test': migration_files + migration_tls_files, + #'migration-test': migration_files + migration_tls_files, 'pxe-test': files('boot-sector.c'), 'pnv-xive2-test': files('pnv-xive2-common.c', 'pnv-xive2-flush-sync.c'), 'qos-test': [chardev, io, qos_test_ss.apply({}).sources()], diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index 18d3cf4ae00..e3f8bca0150 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -116,20 +116,6 @@ run-gdbstub-catch-syscalls: catch-syscalls --bin $< --test $(MULTIARCH_SRC)/gdbstub/catch-syscalls.py, \ hitting a syscall catchpoint) -run-gdbstub-follow-fork-mode-child: follow-fork-mode - $(call run-test, $@, $(GDB_SCRIPT) \ - --gdb $(GDB) \ - --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ - --bin $< --test $(MULTIARCH_SRC)/gdbstub/follow-fork-mode-child.py, \ - following children on fork) - -run-gdbstub-follow-fork-mode-parent: follow-fork-mode - $(call run-test, $@, $(GDB_SCRIPT) \ - --gdb $(GDB) \ - --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ - --bin $< --test $(MULTIARCH_SRC)/gdbstub/follow-fork-mode-parent.py, \ - following parents on fork) - else run-gdbstub-%: $(call skip-test, "gdbstub test $*", "need working gdb with $(patsubst -%,,$(TARGET_NAME)) support") @@ -137,8 +123,7 @@ endif EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read \ run-gdbstub-proc-mappings run-gdbstub-thread-breakpoint \ run-gdbstub-registers run-gdbstub-prot-none \ - run-gdbstub-catch-syscalls run-gdbstub-follow-fork-mode-child \ - run-gdbstub-follow-fork-mode-parent \ + run-gdbstub-catch-syscalls \ run-gdbstub-qxfer-siginfo-read # ARM Compatible Semi Hosting Tests diff --git a/tests/tcg/multiarch/follow-fork-mode.c b/tests/tcg/multiarch/follow-fork-mode.c deleted file mode 100644 index cb6b032b388..00000000000 --- a/tests/tcg/multiarch/follow-fork-mode.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Test GDB's follow-fork-mode. - * - * fork() a chain of processes. - * Parents sends one byte to their children, and children return their - * position in the chain, in order to prove that they survived GDB's fork() - * handling. - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ -#include -#include -#include -#include - -void break_after_fork(void) -{ -} - -int main(void) -{ - int depth = 42, err, i, fd[2], status; - pid_t child, pid; - ssize_t n; - char b; - - for (i = 0; i < depth; i++) { - err = pipe(fd); - assert(err == 0); - child = fork(); - break_after_fork(); - assert(child != -1); - if (child == 0) { - close(fd[1]); - - n = read(fd[0], &b, 1); - close(fd[0]); - assert(n == 1); - assert(b == (char)i); - } else { - close(fd[0]); - - b = (char)i; - n = write(fd[1], &b, 1); - close(fd[1]); - assert(n == 1); - - pid = waitpid(child, &status, 0); - assert(pid == child); - assert(WIFEXITED(status)); - return WEXITSTATUS(status) - 1; - } - } - - return depth; -} diff --git a/tests/tcg/multiarch/gdbstub/follow-fork-mode-child.py b/tests/tcg/multiarch/gdbstub/follow-fork-mode-child.py deleted file mode 100644 index 72a6e440c08..00000000000 --- a/tests/tcg/multiarch/gdbstub/follow-fork-mode-child.py +++ /dev/null @@ -1,40 +0,0 @@ -"""Test GDB's follow-fork-mode child. - -SPDX-License-Identifier: GPL-2.0-or-later -""" -from test_gdbstub import main, report - - -def run_test(): - """Run through the tests one by one""" - gdb.execute("set follow-fork-mode child") - # Check that the parent breakpoints are unset. - gdb.execute("break break_after_fork") - # Check that the parent syscall catchpoints are unset. - # Skip this check on the architectures that don't have them. - have_fork_syscall = False - for fork_syscall in ("fork", "clone", "clone2", "clone3"): - try: - gdb.execute("catch syscall {}".format(fork_syscall)) - except gdb.error: - pass - else: - have_fork_syscall = True - gdb.execute("continue") - for i in range(42): - if have_fork_syscall: - # syscall entry. - if i % 2 == 0: - # Check that the parent single-stepping is turned off. - gdb.execute("si") - else: - gdb.execute("continue") - # syscall exit. - gdb.execute("continue") - # break_after_fork() - gdb.execute("continue") - exitcode = int(gdb.parse_and_eval("$_exitcode")) - report(exitcode == 42, "{} == 42".format(exitcode)) - - -main(run_test) diff --git a/tests/tcg/multiarch/gdbstub/follow-fork-mode-parent.py b/tests/tcg/multiarch/gdbstub/follow-fork-mode-parent.py deleted file mode 100644 index 5c2fe722088..00000000000 --- a/tests/tcg/multiarch/gdbstub/follow-fork-mode-parent.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Test GDB's follow-fork-mode parent. - -SPDX-License-Identifier: GPL-2.0-or-later -""" -from test_gdbstub import main, report - - -def run_test(): - """Run through the tests one by one""" - gdb.execute("set follow-fork-mode parent") - gdb.execute("continue") - exitcode = int(gdb.parse_and_eval("$_exitcode")) - report(exitcode == 0, "{} == 0".format(exitcode)) - - -main(run_test) diff --git a/tests/tcg/multiarch/munmap-pthread.c b/tests/tcg/multiarch/munmap-pthread.c deleted file mode 100644 index 1c79005846d..00000000000 --- a/tests/tcg/multiarch/munmap-pthread.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Test that munmap() and thread creation do not race. */ -#include -#include -#include -#include -#include -#include -#include - -#include "nop_func.h" - -static void *thread_mmap_munmap(void *arg) -{ - volatile bool *run = arg; - char *p; - int ret; - - while (*run) { - p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - assert(p != MAP_FAILED); - - /* Create a small translation block. */ - memcpy(p, nop_func, sizeof(nop_func)); - ((void(*)(void))p)(); - - ret = munmap(p, getpagesize()); - assert(ret == 0); - } - - return NULL; -} - -static void *thread_dummy(void *arg) -{ - return NULL; -} - -int main(void) -{ - pthread_t mmap_munmap, dummy; - volatile bool run = true; - int i, ret; - - /* Without a template, nothing to test. */ - if (sizeof(nop_func) == 0) { - return EXIT_SUCCESS; - } - - ret = pthread_create(&mmap_munmap, NULL, thread_mmap_munmap, (void *)&run); - assert(ret == 0); - - for (i = 0; i < 1000; i++) { - ret = pthread_create(&dummy, NULL, thread_dummy, NULL); - assert(ret == 0); - ret = pthread_join(dummy, NULL); - assert(ret == 0); - } - - run = false; - ret = pthread_join(mmap_munmap, NULL); - assert(ret == 0); - - return EXIT_SUCCESS; -} diff --git a/tests/tcg/multiarch/signals.c b/tests/tcg/multiarch/signals.c deleted file mode 100644 index 998c8fdefd6..00000000000 --- a/tests/tcg/multiarch/signals.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * linux-user signal handling tests. - * - * Copyright (c) 2021 Linaro Ltd - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void error1(const char *filename, int line, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "%s:%d: ", filename, line); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - exit(1); -} - -static int __chk_error(const char *filename, int line, int ret) -{ - if (ret < 0) { - error1(filename, line, "%m (ret=%d, errno=%d/%s)", - ret, errno, strerror(errno)); - } - return ret; -} - -#define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__) - -#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret)) - -/* - * Thread handling - */ -typedef struct ThreadJob ThreadJob; - -struct ThreadJob { - int number; - int sleep; - int count; -}; - -static pthread_t *threads; -static int max_threads = 10; -__thread int signal_count; -int total_signal_count; - -static void *background_thread_func(void *arg) -{ - ThreadJob *job = (ThreadJob *) arg; - - printf("thread%d: started\n", job->number); - while (total_signal_count < job->count) { - usleep(job->sleep); - } - printf("thread%d: saw %d alarms from %d\n", job->number, - signal_count, total_signal_count); - return NULL; -} - -static void spawn_threads(void) -{ - int i; - threads = calloc(sizeof(pthread_t), max_threads); - - for (i = 0; i < max_threads; i++) { - ThreadJob *job = calloc(sizeof(ThreadJob), 1); - job->number = i; - job->sleep = i * 1000; - job->count = i * 100; - pthread_create(threads + i, NULL, background_thread_func, job); - } -} - -static void close_threads(void) -{ - int i; - for (i = 0; i < max_threads; i++) { - pthread_join(threads[i], NULL); - } - free(threads); - threads = NULL; -} - -static void sig_alarm(int sig, siginfo_t *info, void *puc) -{ - if (sig != SIGRTMIN) { - error("unexpected signal"); - } - signal_count++; - __atomic_fetch_add(&total_signal_count, 1, __ATOMIC_SEQ_CST); -} - -static void test_signals(void) -{ - struct sigaction act; - struct itimerspec it; - timer_t tid; - struct sigevent sev; - - /* Set up SIG handler */ - act.sa_sigaction = sig_alarm; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_SIGINFO; - chk_error(sigaction(SIGRTMIN, &act, NULL)); - - /* Create POSIX timer */ - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIGRTMIN; - sev.sigev_value.sival_ptr = &tid; - chk_error(timer_create(CLOCK_REALTIME, &sev, &tid)); - - it.it_interval.tv_sec = 0; - it.it_interval.tv_nsec = 1000000; - it.it_value.tv_sec = 0; - it.it_value.tv_nsec = 1000000; - chk_error(timer_settime(tid, 0, &it, NULL)); - - spawn_threads(); - - do { - usleep(1000); - } while (total_signal_count < 2000); - - printf("shutting down after: %d signals\n", total_signal_count); - - close_threads(); - - chk_error(timer_delete(tid)); -} - -int main(int argc, char **argv) -{ - test_signals(); - return 0; -} diff --git a/tests/tcg/multiarch/vma-pthread.c b/tests/tcg/multiarch/vma-pthread.c deleted file mode 100644 index 7045da08fc4..00000000000 --- a/tests/tcg/multiarch/vma-pthread.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Test that VMA updates do not race. - * - * SPDX-License-Identifier: GPL-2.0-or-later - * - * Map a contiguous chunk of RWX memory. Split it into 8 equally sized - * regions, each of which is guaranteed to have a certain combination of - * protection bits set. - * - * Reader, writer and executor threads perform the respective operations on - * pages, which are guaranteed to have the respective protection bit set. - * Two mutator threads change the non-fixed protection bits randomly. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nop_func.h" - -#define PAGE_IDX_BITS 10 -#define PAGE_COUNT (1 << PAGE_IDX_BITS) -#define PAGE_IDX_MASK (PAGE_COUNT - 1) -#define REGION_IDX_BITS 3 -#define PAGE_IDX_R_MASK (1 << 7) -#define PAGE_IDX_W_MASK (1 << 8) -#define PAGE_IDX_X_MASK (1 << 9) -#define REGION_MASK (PAGE_IDX_R_MASK | PAGE_IDX_W_MASK | PAGE_IDX_X_MASK) -#define PAGES_PER_REGION (1 << (PAGE_IDX_BITS - REGION_IDX_BITS)) - -struct context { - int pagesize; - char *ptr; - int dev_null_fd; - volatile int mutator_count; -}; - -static void *thread_read(void *arg) -{ - struct context *ctx = arg; - ssize_t sret; - size_t i, j; - int ret; - - for (i = 0; ctx->mutator_count; i++) { - char *p; - - j = (i & PAGE_IDX_MASK) | PAGE_IDX_R_MASK; - p = &ctx->ptr[j * ctx->pagesize]; - - /* Read directly. */ - ret = memcmp(p, nop_func, sizeof(nop_func)); - if (ret != 0) { - fprintf(stderr, "fail direct read %p\n", p); - abort(); - } - - /* Read indirectly. */ - sret = write(ctx->dev_null_fd, p, 1); - if (sret != 1) { - if (sret < 0) { - fprintf(stderr, "fail indirect read %p (%m)\n", p); - } else { - fprintf(stderr, "fail indirect read %p (%zd)\n", p, sret); - } - abort(); - } - } - - return NULL; -} - -static void *thread_write(void *arg) -{ - struct context *ctx = arg; - struct timespec *ts; - size_t i, j; - int ret; - - for (i = 0; ctx->mutator_count; i++) { - j = (i & PAGE_IDX_MASK) | PAGE_IDX_W_MASK; - - /* Write directly. */ - memcpy(&ctx->ptr[j * ctx->pagesize], nop_func, sizeof(nop_func)); - - /* Write using a syscall. */ - ts = (struct timespec *)(&ctx->ptr[(j + 1) * ctx->pagesize] - - sizeof(struct timespec)); - ret = clock_gettime(CLOCK_REALTIME, ts); - if (ret != 0) { - fprintf(stderr, "fail indirect write %p (%m)\n", ts); - abort(); - } - } - - return NULL; -} - -static void *thread_execute(void *arg) -{ - struct context *ctx = arg; - size_t i, j; - - for (i = 0; ctx->mutator_count; i++) { - j = (i & PAGE_IDX_MASK) | PAGE_IDX_X_MASK; - ((void(*)(void))&ctx->ptr[j * ctx->pagesize])(); - } - - return NULL; -} - -static void *thread_mutate(void *arg) -{ - size_t i, start_idx, end_idx, page_idx, tmp; - struct context *ctx = arg; - unsigned int seed; - int prot, ret; - - seed = (unsigned int)time(NULL); - for (i = 0; i < 10000; i++) { - start_idx = rand_r(&seed) & PAGE_IDX_MASK; - end_idx = rand_r(&seed) & PAGE_IDX_MASK; - if (start_idx > end_idx) { - tmp = start_idx; - start_idx = end_idx; - end_idx = tmp; - } - prot = rand_r(&seed) & (PROT_READ | PROT_WRITE | PROT_EXEC); - for (page_idx = start_idx & REGION_MASK; page_idx <= end_idx; - page_idx += PAGES_PER_REGION) { - if (page_idx & PAGE_IDX_R_MASK) { - prot |= PROT_READ; - } - if (page_idx & PAGE_IDX_W_MASK) { - /* FIXME: qemu syscalls check for both read+write. */ - prot |= PROT_WRITE | PROT_READ; - } - if (page_idx & PAGE_IDX_X_MASK) { - prot |= PROT_EXEC; - } - } - ret = mprotect(&ctx->ptr[start_idx * ctx->pagesize], - (end_idx - start_idx + 1) * ctx->pagesize, prot); - assert(ret == 0); - } - - __atomic_fetch_sub(&ctx->mutator_count, 1, __ATOMIC_SEQ_CST); - - return NULL; -} - -int main(void) -{ - pthread_t threads[5]; - struct context ctx; - size_t i; - int ret; - - /* Without a template, nothing to test. */ - if (sizeof(nop_func) == 0) { - return EXIT_SUCCESS; - } - - /* Initialize memory chunk. */ - ctx.pagesize = getpagesize(); - ctx.ptr = mmap(NULL, PAGE_COUNT * ctx.pagesize, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - assert(ctx.ptr != MAP_FAILED); - for (i = 0; i < PAGE_COUNT; i++) { - memcpy(&ctx.ptr[i * ctx.pagesize], nop_func, sizeof(nop_func)); - } - ctx.dev_null_fd = open("/dev/null", O_WRONLY); - assert(ctx.dev_null_fd >= 0); - ctx.mutator_count = 2; - - /* Start threads. */ - ret = pthread_create(&threads[0], NULL, thread_read, &ctx); - assert(ret == 0); - ret = pthread_create(&threads[1], NULL, thread_write, &ctx); - assert(ret == 0); - ret = pthread_create(&threads[2], NULL, thread_execute, &ctx); - assert(ret == 0); - for (i = 3; i <= 4; i++) { - ret = pthread_create(&threads[i], NULL, thread_mutate, &ctx); - assert(ret == 0); - } - - /* Wait for threads to stop. */ - for (i = 0; i < sizeof(threads) / sizeof(threads[0]); i++) { - ret = pthread_join(threads[i], NULL); - assert(ret == 0); - } - - /* Destroy memory chunk. */ - ret = close(ctx.dev_null_fd); - assert(ret == 0); - ret = munmap(ctx.ptr, PAGE_COUNT * ctx.pagesize); - assert(ret == 0); - - return EXIT_SUCCESS; -}